<?php

class PayTtService
{
    private $appId;

    private $toutiaoUrl;

    private $toutiaoGetBanacleUri;

    private $toutiaoDeductUri;

    /**
     * @var PayTtService
     */
    private static $instance;

    /**
     * Get the instance of PayTtService
     * @return RechargeService
     */
    public static function get()
    {
        if (!self::$instance) {
            self::$instance = new PayTtService();
        }
        return self::$instance;
    }

    /**
     * Construction.
     */
    public function __construct()
    {
        $configs = SzConfig::get()->loadAppConfig(ModuleSns::getSnsConfigFileName('tt'), null, true);

        $this->appId = $configs['appId']['value'];
        $this->toutiaoUrl = $configs['toutiaoUrl']['value'];
        $this->toutiaoGetBanacleUri = $configs['toutiaoGetBanacleUri']['value'];
        $this->toutiaoDeductUri = $configs['toutiaoDeductUri']['value'];
    }


    /**
     * 充值验证接口
     * @param $userId
     * @param $type
     * @param $indexId
     * @param $count
     * @param $platform
     * @param $reqTime
     * @param $version
     * @return array|bool|void
     * @throws SzException
     */
    public function ttRechargePre($userId, $type, $indexId, $count, $platform, $reqTime, $version)
    {
        //获取玩家openid
        $tempOpenid = UserService::get()->getPlatformId($userId, 'tt');
        $openId = substr($tempOpenid, 0, strlen($tempOpenid));

        $orderId = '';//自定义订单号
        //分支验证充值礼包是否符合购买条件
        $results = $this->branchCheck($userId, $type, $indexId, $count, $reqTime);
        $price = $results['price'];


        //生成订单
        $bill_no = $this->genBillNo($userId, $reqTime);

        $accessToken = PlatformTT::get()->getAccessToken();
        $results['orderId'] = $bill_no;

        //判断钻石是不是首充  type=2
        $isFirstPay = 0;
        if ($type == 2) {
            $activityFirstPayList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_ACTIVITY_FIRST_PAY);
            $activityFirstPay = $activityFirstPayList->getElement($price, false);
            if (!$activityFirstPay) {
                $isFirstPay = 1;
            }
        }

        //签名
        $params = [
            'openid' => (string)$openId,//平台用户ID
            'appid' => $this->appId,//appid
            'ts' => $reqTime,//请求时间
            'zone_id' => '1',//服务大区：1（固定值）
            'pf' => $platform,//平台
            'access_token' => $accessToken//调用凭证
        ];

        $sign = PlatformTT::get()->getSign($params,$this->toutiaoGetBanacleUri);//获取余额的签名
        error_log('tt_sign==>'.$sign."\r\n",3,$_ENV['LOG_ROOT'] . '/payment-' . date('Y-m-d') . '.log');
        $params['mp_sig'] = $sign;

        ksort($params);
        $url = $this->toutiaoUrl.$this->toutiaoGetBanacleUri;
        $res = PlatformTT::get()->postHttpRequest($url, json_encode($params));
        error_log('tt_errcode==>'.$res['errcode']."\r\n",3, $_ENV['LOG_ROOT'] . '/payment-' . date('Y-m-d') . '.log');
        error_log('tt_blance==>'.$res['balance']."\r\n",3, $_ENV['LOG_ROOT'] . '/payment-' . date('Y-m-d') . '.log');
//        if ($res['errcode'] == 0){
            //进行订单预下单存储
            /**
             * @var SzMySqlModel $paymentModel
             * @var ModulePaymentOrderVoList $paymentList
             * @var ModulePaymentOrderVo $payment
             */

            $saveArr = array(
                'userId' => $userId,
                'type' => $type,
                'goodId' => $indexId,
                'count' => $count,
                'price' => $price,
                'ver' => $version,
                'isFirstPay' => $isFirstPay,
                'platform' => $platform
            );
            $saveStr = json_encode($saveArr);

            $creatId = null;
            $paymentModel = SzPersister::get()->getModel(ModulePaymentConst::ORM_NAME_PAYMENT_ORDER);
            $paymentList = SzPersister::get()->getVoList(null, ModulePaymentConst::ORM_NAME_PAYMENT_ORDER, $userId);
            $payment = new ModulePaymentOrderVo(
                $creatId, // orderId
                $userId, // userId
                '', // 平台订单号
                $bill_no, // 游戏订单号
                $reqTime, // orderTime
                0, // completeTime
                0, // status
                $saveStr, // extra
                $price, // price
                true
            );
            list(, $orderId) = $paymentModel->insert($payment);
            if ($orderId) {
                $payment->setOrderId($orderId);
                $payment->removeInsertFlag();
                $payment->persist();
                $paymentList->setElement($orderId, $payment);
                $paymentModel->setListOfVoCache(array($payment), $paymentList->getList());
            } else {
                throw new SzException(30503, 'createOrder', ModulePaymentConst::MODULE_NAME);
            }
//        } else {
//            throw new SzException(20076, 'createOrder', ModulePaymentConst::MODULE_NAME);
//        }

        $ext = "{\"orderId\":\"$bill_no\",\"userId\":\"$userId\",\"ver\":\"$version\",\"goodId\":\"$indexId\",\"count\":\"$count\",\"price\":\"$price\",\"type\":\"$type\",\"isFirstPay\":\"$isFirstPay\",\"platform\":\"$platform\"}";
        $results['ext'] = $ext;
        $realPay = $price;
        /*   if ($res['balance'] >=$price){
               $realPay = 0;
           }*/
        $results['realPay'] = $realPay;

        if ($results['code'] == 0) {
            //充值测试白名单
            if (in_array($userId, GameConst::GAME_TT_TEST_USERID)) {
                $results['realPay'] = 10;
            }
        }

        return $results;
    }


    /**
     * 扣除游戏币
     * @param $userId
     * @param $amt
     * @param $bill_no
     * @param $platform
     * @param $reqTime
     * @return mixed|null
     */
    public function ttDeduct($userId, $amt, $bill_no, $platform, $reqTime)
    {
        //获取玩家openid
        $tempOpenid = UserService::get()->getPlatformId($userId, 'tt');
        $openId = substr($tempOpenid, 0, strlen($tempOpenid));
        $accessToken = PlatformTT::get()->getAccessToken();

        //签名
        $params = [
            'openid' => (string)$openId,//平台用户ID
            'appid' => $this->appId,//appid
            'ts' => $reqTime,//请求时间
            'zone_id' => '1',//服务大区：1（固定值）
            'pf' => $platform,//平台
            'access_token' => $accessToken,//调用凭证
            'amt' => $amt,//扣除游戏币数量，不能为 0
            'bill_no' => $bill_no,//订单号(业务方)
        ];

        $sign = PlatformTT::get()->getSign($params, $this->toutiaoDeductUri);//获取签名
        error_log('tt_deduct__sign==>' . $sign . "\r\n", 3, $_ENV['LOG_ROOT'] . '/payment-' . date('Y-m-d') . '.log');
        $params['mp_sig'] = $sign;

        ksort($params);
        $url = $this->toutiaoUrl . $this->toutiaoDeductUri;
        $res = PlatformTT::get()->postHttpRequest($url, json_encode($params));
        error_log('tt_deduct_errcode==>' . $res['errcode'] . "\r\n", 3, $_ENV['LOG_ROOT'] . '/payment-' . date('Y-m-d') . '.log');

        return $res;
    }

    /**
     * 生成流水号
     * @param int $userId
     * @param int $time
     * @return string
     */
    public function genBillNo($userId, $time)
    {
        return SzUtility::genMd5(uniqid($userId . '_' . $time, false));
    }

    /**
     * 验证逻辑分支
     * @param $userId
     * @param $type
     * @param $indexId
     * @param $count
     * @param $reqTime
     * @return array|bool|void
     * @throws SzException
     */
    public function branchCheck($userId, $type, $indexId, $count, $reqTime)
    {
        $res = array(
            'code' => -1,
            'type' => $type,
            'id' => $indexId,
            'num' => $count,
            'price' => 0
        );

        $changeRes = array();
        $giftConf = array();
        //充值购买物品配置表获取==>1:ft_diamond_gift_pack---2:ft_game_pay---3:ft_diamond_value
        if ($type == 1) {//等级段礼包礼包和玫瑰礼包
            $giftConf = SzConfig::get()->loadAppConfig(GameConst::CONFIG_DIAMOND_GIFT_PACK, $indexId, true);
            if (!empty($giftConf)) {
                $changeRes = $this->checkDiamondGiftPack($userId, $giftConf, $reqTime);
            }
        }
        if ($type == 2) {//钻石，钻石页签的内容
            $giftConf = SzConfig::get()->loadAppConfig(GameConst::CONFIG_GAME_PAY, $indexId, true);
            if (!empty($giftConf)) {
                $batch = 9;//射爆，这个设计很有特色
                $changeRes = $this->checkGamePay($userId, $giftConf, $reqTime, $batch);
            }
        }
        if ($type == 3) {//钻石价值表，金币页签和特惠页签的内容
            $giftConf = SzConfig::get()->loadAppConfig(GameConst::CONFIG_DIAMOND_VALUE, $indexId, true);
            if (!empty($giftConf)) {
                $changeRes = $this->checkDiamondValue($userId, $giftConf);
            }
        }

        if (empty($giftConf)) {
            return $res;
        }

        if (!empty($changeRes)) {
            $res['code'] = $changeRes['code'];
            $res['price'] = $changeRes['price'];
        }

        return $res;
    }

    /**
     * ft_diamond_gift_pack验证
     * @param $userId
     * @param $giftConf
     * @param $reqTime
     * @return array
     * @throws SzException
     */
    public function checkDiamondGiftPack($userId, $giftConf, $reqTime)
    {
        $giftPackageId = $giftConf['giftPackageId'];
        $res = array(
            'code' => 0,
            'price' => $giftConf['price'],
        );

        /**
         * @var $userGiftPackList GiftPackVoList
         * @var $userGiftPack GiftPackVo
         */
        $userGiftPackList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_GIFT_PACK);
        $userGiftPack = $userGiftPackList->getElement($giftPackageId, false);

        //获取巡回礼包配置
        $tourGiftConfs = SzConfig::get()->loadAppConfig(GameConst::CONFIG_GAME_TOUR, null, true, false);
        if (!$tourGiftConfs || empty($tourGiftConfs)) {
            $res['code'] = -1;//配置不存在
            return $res;
        }

        //获取使用配置
        $key = 0;
        $useConf = array();
        $needGiftArr = array();
        $isTourGift = false;
        foreach ($tourGiftConfs as $id => $data) {
            if (in_array($giftPackageId, $data['giftId'])) {
                $key = $id;
                $useConf = $data;
                $needGiftArr = $data['giftId'];
                $isTourGift = true;
                break;
            }
        }

        //非巡回礼包验证
        if (!in_array($giftPackageId, $needGiftArr)) {
            if (!$userGiftPack) {
                $res['code'] = -2;//数据不存在
                return $res;
            }

            if ($userGiftPack->getStatus()) {
                $res['code'] = -3;//礼包未购买
                return $res;
            }

            if ($giftConf['type'] != 4) {
                if ($reqTime < $userGiftPack->getStartTime() || $reqTime > ($userGiftPack->getEndTime() + 600)) {
                    $res['code'] = -4;//礼包购买已经过期
                    return $res;
                }
            }
        }

        //巡回礼包验证
        if ($isTourGift && (empty($key) || empty($useConf) || empty($needGiftArr))) {
            $res['code'] = -1;//配置不存在
            return $res;
        }

        //返回值
        return $res;
    }

    /**
     * ft_game_pay验证
     * @param $userId
     * @param $giftConf
     * @param $reqTime
     * @param $batch
     * @return array
     */
    public function checkGamePay($userId, $giftConf, $reqTime, $batch)
    {
        $money = $giftConf['price'] * 10;
        $res = array(
            'code' => 0,
            'price' => $money,
        );

        $activity = SzConfig::get()->loadAppConfig(GameConst::CONFIG_GAME_EVENT, $batch, true);
        $startTime = $activity['startTime'];
        $endTime = $activity['endTime'];

        //平台活动时间区分
        $platform = UserService::get()->getInfo($userId, GameConst::USER_INFO_TYPE_USER_PLATFORM);
        $platformPre = GameConst::PLATFORM_TIME_ARRAY[$platform];
        if ($platform != 'dev') {
            $startTime = strtotime($activity[$platformPre . 'TriggerTime']);
            $endTime = strtotime($activity[$platformPre . 'EndTime']);
        }

        if ($startTime > $reqTime || $endTime <= ($reqTime + 100)) {
            $res['code'] = -5;//不在活动时间之内
        }

        if ($activity['type'] != ActivityService::ActivityFirstPay) {
            $res['code'] = -6;//非首冲活动类型
        }

        return $res;
    }

    /**
     * ft_diamond_value验证
     * @param $userId
     * @param $giftConf
     * @return array
     * @throws SzException
     */
    public function checkDiamondValue($userId, $giftConf)
    {
        $indexId = $giftConf['indexId'];
        $res = array(
            'code' => 0,
            'price' => $giftConf['price'],
        );

        $diamondSetting = SzConfig::get()->loadAppConfig(GameConst::CONFIG_DIAMOND_VALUE, $indexId, true);
        if (!$diamondSetting) {
            $res['code'] = -1;//配置不存在
            return $res;
        }

        // 每日礼包 && 每周礼包
        if ($diamondSetting['type'] == 6 || $diamondSetting['type'] == 9) {
            /**
             * @var  $dailyGiftPackList DailyGiftPackVoList
             * @var $dailyGiftPack DailyGiftPackVo
             */
            $reqTime = GameService::get()->getReqTime();
            $dailyGiftPackList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_DAILY_GIFT_PACK);
            $dailyGiftPack = $dailyGiftPackList->getElement($indexId, false);
            if (!$dailyGiftPack) {
                $dailyGiftPack = new DailyGiftPackVo($userId, $indexId, 0, true);
            }

            $updateTime = $dailyGiftPack->getUpdateTime();
            if ($diamondSetting['type'] == 6) {
                if (date('Ymd', $updateTime) == date('Ymd', $reqTime)) {
                    $res['code'] = -7;//今日已经购买
                }
            }

            if ($diamondSetting['type'] == 9) {
                $weekday = date('w');
                $weekday = ($weekday + 6) % 7;
                $date = date('Y-m-d', strtotime("-{$weekday} day"));
                $startTime = strtotime($date);
                $endTime = $startTime + 86400 * 7;
                if ($startTime <= $updateTime && $updateTime < $endTime) {
                    $res['code'] = -8;//每周礼包购买时间错误
                }
            }
            return $res;
        }

        // 周年庆
        if ($diamondSetting['type'] == 13) {
            //验证活动是否开启
            $anniversaryAid = ActivityAnniversaryService::get()->getAnniversaryIndexId($userId);
            if ($anniversaryAid) {
                /**
                 * @var AnniversaryStepVoList $anniversaryStepList
                 * @var AnniversaryStepVo $anniversaryStep
                 */
                //获取玩家当前购买阶梯礼包的数据
                $anniversaryStepList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_ACTIVITY_ANNIVERSARY_STEP);
                $anniversaryStep = $anniversaryStepList->getElement($anniversaryAid, false);
                if ($anniversaryStep) {
                    $step = $anniversaryStep->getBuyStep();
                    if ($step + 10000 != $diamondSetting['order']) {
                        $res['code'] = -9;//周年庆阶梯礼包错误
                    }
                }
                else{
                    $res['code'] = -15;//周年庆阶梯礼包数据错误
                }
            }
            else{
                $res['code'] = -13;//周年庆活动数据错误
            }

            return $res;
        }

        //基金成长
        if ($diamondSetting['type'] == 17) {
            /**
             * @var FundInfoVoList $fundInfoList
             * @var FundInfoVo $fundInfo
             */
            $fundInfoList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_FUND_INFO);
            $fundInfo = $fundInfoList->getElement($diamondSetting['indexId'], false);
            if (!$fundInfo) {
                $res['code'] = -13;//没有触发基金
            }
        }

        //合约系统
        if ($diamondSetting['type'] == 15 || $diamondSetting['type'] == 16) {
            //平台活动时间区分
            $platform = UserService::get()->getInfo($userId, GameConst::USER_INFO_TYPE_USER_PLATFORM);
            $platformPre = GameConst::PLATFORM_TIME_ARRAY[$platform];
            //获取合约系统的相关配置
            $contractConf = SzConfig::get()->loadAppConfig(GameConst::CONFIG_GAME_EVENT, null, true);
            //当前时间获取
            $nowTime = GameService::get()->getReqTime();
            $useConf = array();
            $contractStart = 0;
            $contractEnd = 0;
            $isNomal = false;
            $isPoint = false;

            foreach ($contractConf as $aid => $conf) {
                if ($conf['functionId'] == GameConst::FUNC_CONTRACT_FUNC) {
                    //验证合约期数是否正确
                    if ($platform != 'dev'){
                        $contractStart = strtotime($conf[$platformPre.'TriggerTime']);
                        $contractEnd = strtotime($conf[$platformPre.'EndTime']);
                    }
                    else{
                        $contractStart = $conf['startTime'];
                        $contractEnd = $conf['endTime'];
//test0813
                        $contractStart = strtotime($conf['weixinTriggerTime']);
                        $contractEnd = strtotime($conf['weixinEndTime']);
                    }

                    if ($nowTime >= $contractStart && $nowTime <= $contractEnd) {
                        $useConf = $conf;
                        if ($diamondSetting['type'] == 15) {
                            $isNomal = true;
                        }
                        if ($diamondSetting['type'] == 16) {
                            $isPoint = true;
                        }
                        break;
                    }
                }
            }

            if ($useConf) {
                //获取玩家和合约数据
                /**
                 * @var $contractRewardList ContractRewardVoList
                 * @var $contractReward ContractRewardVo
                 */
                $contractRewardList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_CONTRACT_REWARD);
                $contractReward = $contractRewardList->getElement($useConf['indexId'], false);
                if ($isNomal) {
                    if (!$contractReward) {
                        $res['code'] = -10;//合约奖励数据错误
                    }
                }

                if ($isPoint) {
                    $needPoint = SzConfig::get()->loadAppConfig(ModuleProfileConst::CONFIG_PROFILE, 'contractLevelup', true);
                    //获取玩家合约数据
                    /**
                     * @var $contractDataList ContractDataVoList
                     * @var $contractData ContractDataVo
                     */
                    $contractDataList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_CONTRACT_DATA);
                    $contractData = $contractDataList->getElement($useConf['indexId'], false);
                    //积分配置处理
                    $point = 0;
                    $pointReward = explode(';', $diamondSetting['specialId']);
                    foreach ($pointReward as $key => $msg) {
                        $specialItem = explode(':', $msg);
                        if ($specialItem[0] == GameConst::SPECIAL_ITEM_TYPE_1) {
                            $point += $specialItem[1];
                        }
                    }

                    if ($point) {
                        //增加合约积分
                        $hasPoint = $contractData->getNowPoint();
                        $nowLevel = $newLevel = $contractData->getLevel();
                        if ($hasPoint + $point >= $needPoint['value']) {
                            $newLevel = $nowLevel + 1;
                        }
                        //领奖状态
                        if ($newLevel != $nowLevel + 1) {
                            $res['code'] = -12;//合约等级错误
                        }
                    }
                    else{
                        $res['code'] = -11;//合约积分礼包配置积分错误
                    }
                }
                return $res;
            }
            else{
                $res['code'] = -1;//配置不存在
                return $res;
            }
        }
        return $res;
    }
}
